<?php
#+------------------------------------------------------------------
#| 普通的。
#+------------------------------------------------------------------
#| Author:Janmas Cromwell <janmas-cromwell@outlook.com>
#+------------------------------------------------------------------
namespace app\library\websocket\logic;

use app\library\redis\Redis;

/**
 * 用户存储逻辑
 * fd存储的键名是fd_`hash(user_id)`;
 * userInfo存储的键名是 user_`hash(user_id)`;
 * userId存储的键名是user_`fd`;
 */
class Users
{
	const PREFIX    = 'user_';
	const FD_PREFIX = 'fd_';

	/**
	 * 根据加密的UserId获取UserInfo
	 * @param string $userId
	 * @param string $field
	 */
	static function getUserById(string $userId, $field = '*')
	{
		$redis = Redis::get();
		if ($field === '*') {
			$userInfo = $redis->hGetAll(self::PREFIX . $userId);
			unset($userInfo['token'], $userInfo['user_id']);
		} else {
			$userInfo = $redis->hGet(self::PREFIX . $userId, $field);
		}
		Redis::put($redis);
		return $userInfo;
	}

	static function getUserByFd(int $fd, $field = '*')
	{
		$redis = Redis::get();
		$userId = $redis->get(self::PREFIX . $fd);
		if ($field === '*') {
			$userInfo = $redis->hGetAll(self::PREFIX . $userId);
			unset($userInfo['token'], $userInfo['user_id']);
		} else {
			$userInfo = $redis->hGet(self::PREFIX . $userId, $field);
		}
		Redis::put($redis);
		return $userInfo;
	}

	/**
	 * 根据fd获取userId
	 * @param int $fd
	 * @return string
	 */
	static function getUserId(int $fd): string
	{
		$redis = Redis::get();
		$userId = $redis->get(self::PREFIX . $fd);
		Redis::put($redis);
		return $userId;
	}

	/**
	 * 根据userId获取fd
	 * @param string $userId
	 * @return int
	 */
	static function getFd(string $userId): int
	{
		$redis = Redis::get();
		$fd = $redis->get(self::FD_PREFIX . $userId);
		Redis::put($redis);
		return (int)$fd;
	}

	/**
	 * 设置用户信息
	 * @param int $fd
	 * @param string $userId
	 * @param array $userInfo
	 * @return bool
	 * @throws \Exception
	 */
	static function setUser(int $fd, string $userId, array $userInfo = []): bool
	{
		$status = false;
		$success = 0;
		$redis = Redis::get();
		$redis->multi();
		$fdState = $redis->set(self::FD_PREFIX . $userId, $fd);
		$userIdState = $redis->set(self::PREFIX . $fd, $userId);
		foreach ($userInfo as $key => $value) {
			if ($redis->hSet(self::PREFIX . $userId, $key, $value))
				++$success;
		}

		if ($fdState && $userIdState && count($userInfo) == $success) {
			$status = true;
			$redis->exec();
		} else {
			$redis->discard();
		}
		Redis::put($redis);

		if ($status) {
			return true;
		}
		throw new \Exception('保存用户信息失败');
	}

	/**
	 * 根据fd清除登陆信息
	 * @param int $fd
	 * @return int
	 */
	static function clearUserByfd(int $fd): bool
	{
		$redis = Redis::get();
		$userId = $redis->get(self::PREFIX . $fd);
		$keyMap = [
			self::PREFIX . $fd,
			self::FD_PREFIX . $userId,
			self::PREFIX . $userId
		];
		$res = $redis->del($keyMap);
		Redis::put($redis);
		return $res;
	}

	/**
	 * 根据userId清楚登录信息
	 * @param string $userId
	 * @return int
	 */
	static function clearUserById(string $userId): bool
	{
		$redis = Redis::get();
		$fd = $redis->get(self::FD_PREFIX . $userId);
		$keyMap = [
			self::PREFIX . $fd,
			self::FD_PREFIX . $userId,
			self::PREFIX . $userId
		];
		$res = $redis->del($keyMap);
		Redis::put($redis);
		return $res;
	}

	/**
	 * 检测用户标识存储的是否一致
	 * @param int $fd
	 * @param string $userId
	 * @return bool
	 */
	static function exists(int $fd, string $userId)
	{
		$redis = Redis::get();
		if ($redis->get(self::FD_PREFIX . $userId) == $fd && $redis->get(self::PREFIX . $fd) == $userId) {
			return true;
		}
		return false;
	}

}
